<?php

/**
 * Pwiff - PHP SWF Library
 *
 * LICENSE
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 *
 * @package    Pwiff
 * @subpackage Utilities
 * @copyright  Copyright (c) 2010 Steven Harris
 * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
 * @version    $Id: Numerics.php 2 2010-02-07 04:10:51Z indigo.sunrise $
 */

/**
 * Utilities for handling numeric operations.
 *
 * @package    Pwiff
 * @subpackage Utilities
 */
class Pwiff_Util_Numerics
{
	/**
	 * Returns a float as a sequence of bits in the form of a 32-bit
	 * unsigned integer.
	 *
	 * @param  float $float
	 * @return int
	 */
	public static function floatToIntBits($float)
	{
		$s = unpack('Vval', pack('f', $float));
		return $s['val'];
	}
	
	/**
	 * Returns the number of bits needed to represent a given signed integer.
	 * If given an array, returns the bits needed to represent the largest
	 * value.
	 *
	 * @param  int|array $number
	 * @return int
	 */
	public static function getSignedBitCount($number)
	{
		if (is_array($number)) {
			return max(array_map(array(__CLASS__, __FUNCTION__), $number));
		}
		
		// with 2's complement, -N takes the same # of bytes as N-1
		if ($number < 0) {
			$number = -$number - 1;
		}
		return self::getUnsignedBitCount($number) + 1;
	}
	
	/**
	 * Returns the number of bits needed to represent a given unsigned integer.
	 * If given an array, returns the bits needed to represent the largest
	 * value.
	 *
	 * @param  int $number
	 * @return int
	 */
	public static function getUnsignedBitCount($number)
	{
		if (is_array($number)) {
			return max(array_map(array(__CLASS__, __FUNCTION__), $number));
		}
		
		$i = 0;
		while ($number > 0) {
			$number >>= 1;
			$i++;
		}
		return $i;
	}
	
	/**
	 * Returns the number of bits needed to represent a given float as a
	 * 16.16 fixed point number. If given an array, returns the bits needed
	 * to represent the largest value.
	 *
	 * @param  float $number
	 * @return int
	 */
	public static function getFixedPointBitCount($number)
	{
		if (is_array($number)) {
			return max(array_map(array(__CLASS__, __FUNCTION__), $number));
		}
		
		return self::getSignedBitCount(intval($number) * 65536);
	}
	
	/**
	 * Returns whether the given unsigned integer can fit within the given
	 * bit count.
	 *
	 * @param  int $integer
	 * @param  int $numBits
	 * @return bool
	 */
	public static function canFitUnsigned($integer, $numBits)
	{
		return ($integer < pow(2, $numBits));
	}
	
	/**
	 * Returns whether the given signed integer can fit within the given
	 * bit count.
	 *
	 * @param  int $integer
	 * @param  int $numBits
	 * @return bool
	 */
	public static function canFitSigned($integer, $numBits)
	{
		return ($integer >= -pow(2, $numBits - 1) AND $integer < pow(2, $numBits - 1));
	}
			
}
